#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

// Valor máximo a ser gerado aleatoriamente
#define MAX 10000

// Função para mensagem de erro e término do programa
void error(const char *msg)
{
	perror(msg);
	exit(0);
}

// Função para completar o vetor com números aleatórios limitados a MAX
void gerarAleatorio(int v[], int tam)
{
	int i;
	srand(time(NULL));

	for(i=0; i<tam; ++i)
		v[i]=(rand()%MAX)+1;
}


int main(int argc, char *argv[])
{
    // Variáveis para conexão com o servidor no nível acima
	int sockfd, portaServidor, resposta;
	struct sockaddr_in serv_addr;
	struct hostent *server;

	char buffer[256];

	// Vetor Original
	int v[125], tam = 125;
	int vord[125];
	int i;
	
	// Vetor Pronto
	int tamPronto;
	int *vetorPronto;
	char confirm[20];
	
	// Variáveis para a contagem do tempo.
	struct timeval t0,t1,t2,t3;
	int tempo;	
	
	strcpy(confirm,"I got your message");

	// Checa se o número de argumentos recebidos está correto
	if (argc != 3)
	   error ("Numero invalido de argumentos");

	// Gerando o vetor aleatório.
	gerarAleatorio(v, 125);
	for(i = 0; i < 125; i++)
        vord[i] = v[i];
	   
	// Configura conexão com o servidor no nível acima
	gettimeofday(&t0, 0);
	portaServidor = atoi(argv[2]);
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
		error("ERRO ao abrir socket");
	server = gethostbyname(argv[1]);
	if (server == NULL)
		error("ERRO host não encontrado");

    // Abre conexão com o servidor no nível acima
	bzero((char *) &serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
	serv_addr.sin_port = htons(portaServidor);
	if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
		error("ERRO ao conectar");

    // Envia o tamanho do vetor
	resposta = write(sockfd,&tam,sizeof(tam));
	if (resposta < 0)
		 error("ERRO ao escrever no socket");

    // Recebe a mensagem de confirmação
	bzero(&buffer,20);
	resposta = read(sockfd, &buffer, 18);
    if(strcmp(buffer,confirm) == 0 && resposta > 0)//tamanho do vetor chegou ao servidor, enviar o vetor
		printf("Tamanho Chegou.\n");
   if (resposta < 0)
		error("ERRO ao ler do socket");

    // Envia o vetor para o servidor
	resposta = write(sockfd, vord, sizeof(int)*125);//enviando vetor
	if (resposta < 0)
		error("ERRO ao escrever no socket");

    // Recebe a mensagem de confirmação
	bzero(&buffer,20);
	resposta = read(sockfd,&buffer,18);
	if(strcmp(buffer,confirm) == 0 && resposta > 0)
		printf("Vetor chegou.\n");
	if (resposta < 0)
		error("ERRO ao ler do socket");
		
	gettimeofday(&t1, 0);
    tempo = t1.tv_usec - t0.tv_usec;
    printf("\nTempo de Evio do vetor: %d \n",tempo);
		
	gettimeofday(&t2, 0);
		
	// Recebe de Volta o Vetor Pronto.
	resposta = read(sockfd, &tamPronto, sizeof(int));
	if (resposta < 0) error("ERROR reading from socket");
	
	vetorPronto = malloc(sizeof(int) * (tamPronto));
	resposta = recv(sockfd,vetorPronto,sizeof(int)*tamPronto,MSG_WAITALL);	
	if (resposta < 0) error("ERROR reading from socket");

	resposta = write(sockfd, confirm, strlen(confirm));
	if (resposta < 0) error("ERROR writing to socket");
	gettimeofday(&t3, 0);
    tempo = t3.tv_usec - t2.tv_usec;
    printf("\nTempo de receber o vetor pronto: %d \n",tempo);
	// Fim da recepcao do vetor pronto
	
	tempo = t3.tv_usec - t0.tv_usec;
    printf("\nTempo Total de geração do Vetor: %d \n",tempo);
		
	printf ("\n****************************Vetor Pronto**********************************\n");
    for (i=0; i<tamPronto; i++)
        printf ("%d ", vetorPronto[i]);
    printf ("\n");
		

	close(sockfd);
	return 0;
}

